#include "HerzeleidPrecompiled.hxx"

#include "HerzeleidCoreApplication.hxx"
#include "HerzeleidConverter.hxx"

#ifdef HERZELEID_GENERATE_CRT_DBG_FILE_REPORT
static HANDLE g__Herzeleid_Assertions_CrtFileHandle = nullptr;
static HANDLE g__Herzeleid_Warnings_CrtFileHandle = nullptr;
static HANDLE g__Herzeleid_Errors_CrtFileHandle = nullptr;
#endif

static void _Herzeleid_CrtStartDebugging()
{
#ifdef HERZELEID_GENERATE_CRT_DBG_FILE_REPORT
#if defined REIGN_DEBUG && defined REIGN_DESKTOP // Debug + Desktop

	SYSTEMTIME time;
	GetLocalTime(&time);
	{
		std::stringstream ss; ss.clear();
		ss << "HerzeleidCrtReport-Assertions";
		ss << "-mo-"; ss << time.wMonth;
		ss << "-da-"; ss << time.wDay;
		ss << "-ye-"; ss << time.wYear;
		ss << "-ho-"; ss << time.wHour;
		ss << "-mi-"; ss << time.wMinute;
		ss << "-se-"; ss << time.wSecond;
		ss << "-ms-"; ss << time.wMilliseconds;
		ss << ".txt\0";

		g__Herzeleid_Assertions_CrtFileHandle = CreateFileA(
			ss.str().data(),
			GENERIC_WRITE, FILE_SHARE_WRITE,
			NoFlags, CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			nullptr
			);
	}
	GetLocalTime(&time);
	{
		std::stringstream ss; ss.clear();
		ss << "HerzeleidCrtReport-Warnings";
		ss << "-mo-"; ss << time.wMonth;
		ss << "-da-"; ss << time.wDay;
		ss << "-ye-"; ss << time.wYear;
		ss << "-ho-"; ss << time.wHour;
		ss << "-mi-"; ss << time.wMinute;
		ss << "-se-"; ss << time.wSecond;
		ss << "-ms-"; ss << time.wMilliseconds;
		ss << ".txt\0";

		g__Herzeleid_Warnings_CrtFileHandle = CreateFileA(
			ss.str().data(),
			GENERIC_WRITE, FILE_SHARE_WRITE,
			NoFlags, CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			nullptr
			);
	}
	GetLocalTime(&time);
	{
		std::stringstream ss; ss.clear();
		ss << "HerzeleidCrtReport-Errors";
		ss << "-mo-"; ss << time.wMonth;
		ss << "-da-"; ss << time.wDay;
		ss << "-ye-"; ss << time.wYear;
		ss << "-ho-"; ss << time.wHour;
		ss << "-mi-"; ss << time.wMinute;
		ss << "-se-"; ss << time.wSecond;
		ss << "-ms-"; ss << time.wMilliseconds;
		ss << ".txt\0";

		g__Herzeleid_Errors_CrtFileHandle = CreateFileA(
			ss.str().data(),
			GENERIC_WRITE, FILE_SHARE_WRITE,
			NoFlags, CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			nullptr
			);
	}

	_CrtSetDbgFlag( // Enable run-time memory check for debug builds.
		_CRTDBG_ALLOC_MEM_DF | // Enable debug allocation
		_CRTDBG_LEAK_CHECK_DF // Enable checking for memory leaks
		);

	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
	PrintToDebugWindowOnly8("Herzeleid. Crt debugging started.");

	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
	_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_ASSERT, g__Herzeleid_Assertions_CrtFileHandle);
	_CrtSetReportFile(_CRT_WARN, g__Herzeleid_Warnings_CrtFileHandle);
	_CrtSetReportFile(_CRT_ERROR, g__Herzeleid_Errors_CrtFileHandle);

	_RPT0(_CRT_ASSERT, "\r\nHerzeleid (Assert). Crt debugging started.\r\n");
	_RPT0(_CRT_ERROR, "\r\nHerzeleid (Error). Crt debugging started.\r\n");
	_RPT0(_CRT_WARN, "\r\nHerzeleid (Warn). Crt debugging started.\r\n");
#endif // All configurations
#elif defined REIGN_DEBUG && defined REIGN_DESKTOP

	_CrtSetDbgFlag( // Enable run-time memory check for debug builds.
		_CRTDBG_ALLOC_MEM_DF | // Enable debug allocation
		_CRTDBG_LEAK_CHECK_DF // Enable checking for memory leaks
		);

	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
	PrintToDebugWindowOnly8("Herzeleid. Crt debugging started.");

#endif
}

static void _Herzeleid_CrtCloseDebugging()
{
#ifdef HERZELEID_GENERATE_CRT_DBG_FILE_REPORT
	_CrtDumpMemoryLeaks();
	_CrtCheckMemory();
	_RPT0(_CRT_ASSERT, "\r\nHerzeleid (Assert). Crt debugging closed.\r\n");
	_RPT0(_CRT_ERROR, "\r\nHerzeleid (Error). Crt debugging closed.\r\n");
	_RPT0(_CRT_WARN, "\r\nHerzeleid (Warn). Crt debugging closed.\r\n");
	if (g__Herzeleid_Assertions_CrtFileHandle) CloseHandle(g__Herzeleid_Assertions_CrtFileHandle);
	if (g__Herzeleid_Warnings_CrtFileHandle) CloseHandle(g__Herzeleid_Warnings_CrtFileHandle);
	if (g__Herzeleid_Errors_CrtFileHandle) CloseHandle(g__Herzeleid_Errors_CrtFileHandle);

	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);

	PrintToDebugWindowOnly8("Herzeleid. Crt debugging closed.");
#elif defined REIGN_DEBUG && defined REIGN_DESKTOP
	PrintToDebugWindowOnly8("Herzeleid. Crt debugging closed.");
#endif
}

static void _Herzeleid_Application(
	_In_ InstanceHandle hInstance
	)
{
	using namespace HerzeleidAppModelCoreNamespaceImpl;
	PrintToDebugWindowOnly8("Herzeleid. Main");
	_Herzeleid_CrtStartDebugging();

	auto App = CoreApplication::Startup(hInstance);
	CoreApplication::Exit();
	Safe_Delete(App);

	_Herzeleid_CrtCloseDebugging();
	PrintToDebugWindowOnly8("Herzeleid. Exiting.");
}

Int32 APIENTRY wWinMain( // UNICODE
	_In_ InstanceHandle hInstance, 
	_In_ InstanceHandle hPrevInstance, 
	_In_ LPWSTR lpCmdLine, // Char16*
	_In_ Int32 nShowCmd 
	)
{
	_Herzeleid_Application(hInstance);
	return( EXIT_SUCCESS );
}

Int32 APIENTRY WinMain( // !UNICODE
	_In_ InstanceHandle hInstance, 
	_In_ InstanceHandle hPrevInstance, 
	_In_ LPSTR lpCmdLine, // Char8*
	_In_ Int32 nShowCmd 
	)
{
	_Herzeleid_Application(hInstance);
	return( EXIT_SUCCESS );
}


